package cn.ad.server.web.spring.service.actions.handler.gdt.server;

import cn.ad.server.common.utils.BeanUtils;
import cn.ad.server.common.utils.EncodeUtils;
import cn.ad.server.web.exception.AdServerMessageException;
import cn.ad.server.web.spring.model.gdt.server.*;
import cn.ad.server.web.spring.model.sts.STSAdResponse;
import cn.ad.server.web.spring.service.actions.context.AdContext;
import cn.ad.server.web.spring.service.components.adtraffic.AdTrafficDispatcherManager;
import cn.ad.server.web.spring.service.components.adtraffic.GDTTrafficDispatcher;
import cn.ad.server.web.utils.JsonUtils;
import cn.ad.server.domain.ad.AdSpace;
import cn.ad.server.domain.ad.AdSpaceAdxMap;
import cn.ad.server.domain.enumration.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Server 2 Server流量分发到GDT处理类
 * @author dongbin.yu
 * @from 2016-09-18
 * @since V2.0
 * @deprecated 此类不推荐使用，降在新的流量分配管理器 {@link AdTrafficDispatcherManager}中完成分发，广电通直接分流将在{@link GDTTrafficDispatcher}中实现
 */
@Component
@Deprecated
public class GDTMobileServerHandler {

    private static Logger logger = LoggerFactory.getLogger(GDTMobileServerHandler.class);

    private final String impAddress = "http://v.gdt.qq.com/gdt_stats.fcg";

    private final String clickAddress = "http://c.gdt.qq.com/gdt_mclick.fcg";

    @Resource
    private String serverAddress;

    @Autowired
    private HttpConnectionManager httpConnectionManager;


    /**
     * 拼装请求参数
     * @param adContext
     * @param returnCode
     * @return
     */
    private Map<String, Object> compositeAdSpace(AdContext adContext, AdSpace localAdSpace, ReturnCode returnCode) {

        Map<String, Object> param = new LinkedHashMap<>();
        param.put("adposcount", "1");
        param.put("count", "1");

        List<AdSpaceAdxMap> adSpaceAdxMaps = localAdSpace.getAdSpaceAdxMaps();
        if (!CollectionUtils.isEmpty(adSpaceAdxMaps)) {
            //FIXME 改成支持数组的请求 且支持计数
            AdSpaceAdxMap adSpaceAdxMap = adSpaceAdxMaps.get(0);
            if (adSpaceAdxMap.getWidth() > 0) {
                param.put("posw", adSpaceAdxMap.getWidth());
                param.put("posh", adSpaceAdxMap.getHeight());
            } else {
                param.put("posw", adContext.getAdSpaceWidth());
                param.put("posh", adContext.getAdSpaceHeight());
            }
            param.put("posid", adSpaceAdxMap.getAdxSpaceId());
            param.put("charset", "utf8");
            param.put("datafmt", "json");

            //广告请求扩展内容
            GdtServerExt gdtServerExt = new GdtServerExt();
            GdtServerReq gdtServerReq = new GdtServerReq();

            // 设置request param
            gdtServerReq.setApiver("2.0");

            //AppId
            gdtServerReq.setAppid(adSpaceAdxMap.getAppId());
            gdtServerReq.setC_os(OS.osMap.get(adContext.getOs()).getName());
            if (adContext.getMuniqueType() == MUniqueType.IMEI.getValue()) {
                if (StringUtils.isNotEmpty(adContext.getImeiori())) {
                    gdtServerReq.setMuid(EncodeUtils.MD5(adContext.getImeiori().toLowerCase()));
                } else {
                    gdtServerReq.setMuid(adContext.getImei());
                }
                gdtServerReq.setMuidtype(GDTMuniqueType.IMEI.getValue());
            } else if (adContext.getMuniqueType() == MUniqueType.IDFA.getValue()) {
                gdtServerReq.setMuidtype(GDTMuniqueType.IFA.getValue());
                gdtServerReq.setMuid(adContext.getIdfa());
            } else if (adContext.getMuniqueType() == MUniqueType.MAC.getValue()) {
                //优先imei传递
                if (StringUtils.isNotEmpty(adContext.getImeiori())) {
                    gdtServerReq.setMuid(EncodeUtils.MD5(adContext.getImeiori().toLowerCase()));
                    gdtServerReq.setMuidtype(GDTMuniqueType.IMEI.getValue());
                } else {
                    gdtServerReq.setMuid(adContext.getMac());
                    gdtServerReq.setMuidtype(GDTMuniqueType.MAC.getValue());
                }
            } else {
                throw new AdServerMessageException(returnCode);
            }

            //FIXME 填了设备后就不能出广告了
            if (adContext.getBrand() != null) {
                gdtServerReq.setC_device(adContext.getBrand());
            } else if (adContext.getModel() != null) {
                gdtServerReq.setC_device(adContext.getModel());
            } else {
                gdtServerReq.setC_device("unknown");
            }

            //App包名
            gdtServerReq.setC_pkgname(adSpaceAdxMap.getPackageName());
            gdtServerReq.setPostype(GDTServerAdFormat.AD_FORMAT_MAP.get(AdFormat.adFormatMap.get(adContext.getAdFormat())));
            gdtServerReq.setConn(adContext.getConnType());
            gdtServerReq.setCarrier(adContext.getMob_ops());
            if (adContext.getScreenOritent() == Orientation.CROSS.ordinal()) {
                gdtServerReq.setC_w(adContext.getScreenHeight());
                gdtServerReq.setC_h(adContext.getScreenWidth());
            } else {
                gdtServerReq.setC_w(adContext.getScreenWidth());
                gdtServerReq.setC_h(adContext.getScreenHeight());
            }
            gdtServerReq.setRemoteip(adContext.getIp());
            if (adContext.getLatitude() != 0.0 && adContext.getLongitude() != 0.0) {
                gdtServerReq.setLat(new BigDecimal(adContext.getLatitude() * 1000000).intValue());
                gdtServerReq.setLng(new BigDecimal(adContext.getLongitude() * 1000000).intValue());
            }

            gdtServerReq.setUseragent(adContext.getUa());
            gdtServerReq.setReferer(adContext.getReferer());
            gdtServerReq.setC_osver(adContext.getOsVersion());
            if (StringUtils.isNotEmpty(adContext.getImeiori())) {
                gdtServerReq.setImei(EncodeUtils.MD5(adContext.getImeiori().toLowerCase()));
            }
            if (adContext.getMac() != null) {
                gdtServerReq.setMac(adContext.getMac());
            }
            if (adContext.getAndroidId() != null) {
                gdtServerReq.setAid(adContext.getAndroidId());
            }
            if (adContext.getAaid() != null) {
                gdtServerReq.setAaid(adContext.getAaid());
            }
            if (adContext.getIdfa() != null) {
                gdtServerReq.setIdfa(adContext.getIdfa());
            }

            gdtServerExt.setReq(gdtServerReq);
            param.put("ext", gdtServerExt);
        } else {
            //处理异常
            throw new AdServerMessageException(returnCode);
        }

        return param;
    }

    public STSAdResponse.AdSpace request(AdContext adContext, STSAdResponse.AdSpace adSpace, AdSpace localAdSpace, ReturnCode returnCode) {

        Map<String, Object> param = compositeAdSpace(adContext, localAdSpace, returnCode);
        //设置转发失败
        adContext.setForwardType(2);
        CloseableHttpClient httpClient = httpConnectionManager.getHttpClient();
        HttpGet httpGet = new HttpGet("http://mi.gdt.qq.com/gdt_mview.fcg?" + generateParam(param));
        InputStream ins = null;
        try {
            CloseableHttpResponse response = httpClient.execute(httpGet);
            ins = response.getEntity().getContent();

            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                //拼接返回参数
                Map result = JsonUtils.toObject(ins, Map.class);
                if ((int) result.get("ret") == 0) {
                    Object imp = ((Map) result.get("data")).get(param.get("posid"));
                    if (imp != null) {
                        Map impMap = (Map) imp;
                        List impList = (List) impMap.get("list");
                        if (!CollectionUtils.isEmpty(impList)) {
                            Map impEntity = (Map) impList.get(0);
                            STSAdResponse.Creative creative = new STSAdResponse.Creative();
                            creative.setImpression(new String[]{compositeImpUrl((String) impEntity.get("viewid"), param)});
                            STSAdResponse.Event event = new STSAdResponse.Event();
                            event.setEventKey(ActionType.LINK_JUMP.getValue());
                            event.setEventValue(impEntity.get("rl") + "&s={'down_x':-999,'down_y':-999,'up_x':-999,'up_y':-999}");
                            creative.setEvent(new STSAdResponse.Event[]{event});
                            creative.setClick(new String[]{compositeLocalClickUrl(adContext)});
                            creative.setAdmark(BeanUtils.convertIosUrl("http://alicdn.lieying.cn/sentshow/imgs/tmp/tsa_ad_logo.png", adContext.getOs()));
                            switch (AdFormat.adFormatMap.get(adContext.getAdFormat())) {

                                case BANNER:
                                case TABLE_SCREEN:
                                case OPEN_SCREEN:
                                    STSAdResponse.Banner banner = new STSAdResponse.Banner();
                                    banner.setWidth((int) param.get("posw"));
                                    banner.setHeight((int) param.get("posh"));
                                    String imgUrl = (String) impEntity.get("img");
                                    if (StringUtils.isEmpty(imgUrl)) {
                                        //处理异常
                                        throw new AdServerMessageException(returnCode);
                                    } else {
                                        banner.setCreativeUrl(BeanUtils.convertIosUrl(imgUrl, adContext.getOs()));
                                    }
                                    banner.setType(MaterialFormat.JPG.getName());
                                    creative.setBanner(banner);
                                    break;
                                case VIDEO:
                                case AD_NATIVE:
                                default:
                                    break;
                            }

                            adSpace.setCreative(new STSAdResponse.Creative[]{creative});
                        } else {
                            //处理异常
                            throw new AdServerMessageException(returnCode);
                        }
                    }
                } else {
                    //处理异常
                    throw new AdServerMessageException(returnCode);
                }
            } else {
                //处理异常
                throw new AdServerMessageException(returnCode);
            }
        } catch (IOException e) {
            logger.error("http://mi.gdt.qq.com/gdt_mview.fcg request error");
            //处理异常
            throw new AdServerMessageException(returnCode);
        }

        adContext.setForwardType(1);
        return adSpace;
    }

    private String generateParam(Map<String,Object> map) {
        List<String> params = new ArrayList<>();
        if (map != null && map.size() > 0) {
            for (Map.Entry entry : map.entrySet()) {
                if (entry.getValue() instanceof String || entry.getValue() instanceof Integer) {
                    params.add(String.format("%s=%s", entry.getKey(), entry.getValue()));
                } else {
                    try {
                        params.add(String.format("%s=%s", entry.getKey(), URLEncoder.encode(JsonUtils.toJson(entry.getValue()),"utf-8")));
                    } catch (UnsupportedEncodingException e) {
                        logger.error("urlencode error");
                    }
                }
            }
        }
        return StringUtils.join(params, "&");
    }

    private String compositeImpUrl(String viewId, Map param) {

        String impUrlFormat = impAddress + "?count=%s&viewid0=%s";
        return String.format(impUrlFormat, param.get("count"), viewId);
    }

    private String compositeLocalClickUrl(AdContext adContext) {
        String impUrlFormat = serverAddress + "redirect.html?version=%s&aid=%s&sid=%s";
        return String.format(impUrlFormat, adContext.getVersion(), adContext.getAdSpaceId(), 0);
    }

}
